Add a draw-border style property to allow themes to draw outside the
authorOwen Taylor <otaylor@redhat.com>
Mon, 2 May 2005 23:29:24 +0000 (23:29 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Mon, 2 May 2005 23:29:24 +0000 (23:29 +0000)
2005-04-28  Owen Taylor  <otaylor@redhat.com>

* gtk/gtkwidget.c: Add a draw-border style property to allow
themes to draw outside the widget's allocation.

* gdk/gdkwindow.c gtk/gtkstyle.c: Remove some save/restore pairs
that were working around the clip-leakage bug in Cairo.

* gtk/gtkstyle.c: Use cairo_fill_preserve() rathe than
save/fill/restore.

* gdk/gdkgc.c gdk/gdkinternals.h: Add _gdk_gc_update_context()
That updates a Cairo context to match a GC.

* gdk/gdkdraw.c: Use _gdk_gc_update_context() to add support
for tiles/stipples/clipping to gdk_draw_glyphs(),
gdk_draw_trapezoids().

* gdk/gdkpango.c: Use _gdk_gc_update_context() instead of internal
implementation of stipples. Use one cairo_t across the entire
drawing operation. Replace cairo_matrix_create() with
stack-allocated matrices.

* gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
gdk/win32/gdkgc-win32.c: Save various aspects of the
GC state (fill, tile, stipple, foreground, background, clip region)
in instance-private-data for future use. Add getters.
Get rid of _gdk_windowing_gc_get_foreground() function implemented
by the backends.

* gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Add
_gdk_gc_init() to do initial setup of the GC from values;
fixes some problems from drawable redirection.

* gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Move
gdk_gc_copy() and gdk_gc_set_clip_{region,rectangle}() into
the generic code, add _gdk_windowing_gc_copy(),
_gdk_windowing_gc_set_clip_region() to do backend specific
stuff.

* gdk/x11/{gdkprivate-x11.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
gdk/win32/{gdkprivate-win32.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
gdk/linux-fb/{gdkprivate-fb.h,gdkgc-fb.c.c,gdkdrawable-fb.c}:
Don't duplicate state that now is stored by the generic code.

* gdk/gdk.symbols Update

20 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
gdk/gdk.symbols
gdk/gdkdraw.c
gdk/gdkgc.c
gdk/gdkinternals.h
gdk/gdkpango.c
gdk/gdkwindow.c
gdk/linux-fb/gdkdrawable-fb2.c
gdk/linux-fb/gdkgc-fb.c
gdk/linux-fb/gdkprivate-fb.h
gdk/win32/gdkdrawable-win32.c
gdk/win32/gdkgc-win32.c
gdk/win32/gdkprivate-win32.h
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkgc-x11.c
gdk/x11/gdkprivate-x11.h
gtk/gtkstyle.c
gtk/gtkwidget.c

index 95bf48c129624f23da065b29b730aca7f63e3dc8..730c7586e65a1f0031fe63f50a644c9dd8c449e4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+2005-04-28  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwidget.c: Add a draw-border style property to allow
+       themes to draw outside the widget's allocation.
+
+       * gdk/gdkwindow.c gtk/gtkstyle.c: Remove some save/restore pairs
+       that were working around the clip-leakage bug in Cairo.
+
+       * gtk/gtkstyle.c: Use cairo_fill_preserve() rathe than
+       save/fill/restore.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h: Add _gdk_gc_update_context()
+       That updates a Cairo context to match a GC.
+
+       * gdk/gdkdraw.c: Use _gdk_gc_update_context() to add support
+       for tiles/stipples/clipping to gdk_draw_glyphs(), 
+       gdk_draw_trapezoids().
+
+       * gdk/gdkpango.c: Use _gdk_gc_update_context() instead of internal
+       implementation of stipples. Use one cairo_t across the entire
+       drawing operation. Replace cairo_matrix_create() with 
+       stack-allocated matrices.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c 
+       gdk/win32/gdkgc-win32.c: Save various aspects of the 
+       GC state (fill, tile, stipple, foreground, background, clip region)
+       in instance-private-data for future use. Add getters.
+       Get rid of _gdk_windowing_gc_get_foreground() function implemented 
+       by the backends.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
+       gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Add
+       _gdk_gc_init() to do initial setup of the GC from values;
+       fixes some problems from drawable redirection.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
+       gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Move 
+       gdk_gc_copy() and gdk_gc_set_clip_{region,rectangle}() into 
+       the generic code, add _gdk_windowing_gc_copy(), 
+       _gdk_windowing_gc_set_clip_region() to do backend specific
+       stuff.
+
+       * gdk/x11/{gdkprivate-x11.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
+       gdk/win32/{gdkprivate-win32.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
+       gdk/linux-fb/{gdkprivate-fb.h,gdkgc-fb.c.c,gdkdrawable-fb.c}:
+       Don't duplicate state that now is stored by the generic code.
+
+       * gdk/gdk.symbols Update
+
 2005-05-02  Matthias Clasen  <mclasen@redhat.com>
 
        * tests/testiconview.c: Test cell renderers.
index 95bf48c129624f23da065b29b730aca7f63e3dc8..730c7586e65a1f0031fe63f50a644c9dd8c449e4 100644 (file)
@@ -1,3 +1,52 @@
+2005-04-28  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwidget.c: Add a draw-border style property to allow
+       themes to draw outside the widget's allocation.
+
+       * gdk/gdkwindow.c gtk/gtkstyle.c: Remove some save/restore pairs
+       that were working around the clip-leakage bug in Cairo.
+
+       * gtk/gtkstyle.c: Use cairo_fill_preserve() rathe than
+       save/fill/restore.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h: Add _gdk_gc_update_context()
+       That updates a Cairo context to match a GC.
+
+       * gdk/gdkdraw.c: Use _gdk_gc_update_context() to add support
+       for tiles/stipples/clipping to gdk_draw_glyphs(), 
+       gdk_draw_trapezoids().
+
+       * gdk/gdkpango.c: Use _gdk_gc_update_context() instead of internal
+       implementation of stipples. Use one cairo_t across the entire
+       drawing operation. Replace cairo_matrix_create() with 
+       stack-allocated matrices.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c 
+       gdk/win32/gdkgc-win32.c: Save various aspects of the 
+       GC state (fill, tile, stipple, foreground, background, clip region)
+       in instance-private-data for future use. Add getters.
+       Get rid of _gdk_windowing_gc_get_foreground() function implemented 
+       by the backends.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
+       gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Add
+       _gdk_gc_init() to do initial setup of the GC from values;
+       fixes some problems from drawable redirection.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
+       gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Move 
+       gdk_gc_copy() and gdk_gc_set_clip_{region,rectangle}() into 
+       the generic code, add _gdk_windowing_gc_copy(), 
+       _gdk_windowing_gc_set_clip_region() to do backend specific
+       stuff.
+
+       * gdk/x11/{gdkprivate-x11.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
+       gdk/win32/{gdkprivate-win32.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
+       gdk/linux-fb/{gdkprivate-fb.h,gdkgc-fb.c.c,gdkdrawable-fb.c}:
+       Don't duplicate state that now is stored by the generic code.
+
+       * gdk/gdk.symbols Update
+
 2005-05-02  Matthias Clasen  <mclasen@redhat.com>
 
        * tests/testiconview.c: Test cell renderers.
index 95bf48c129624f23da065b29b730aca7f63e3dc8..730c7586e65a1f0031fe63f50a644c9dd8c449e4 100644 (file)
@@ -1,3 +1,52 @@
+2005-04-28  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwidget.c: Add a draw-border style property to allow
+       themes to draw outside the widget's allocation.
+
+       * gdk/gdkwindow.c gtk/gtkstyle.c: Remove some save/restore pairs
+       that were working around the clip-leakage bug in Cairo.
+
+       * gtk/gtkstyle.c: Use cairo_fill_preserve() rathe than
+       save/fill/restore.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h: Add _gdk_gc_update_context()
+       That updates a Cairo context to match a GC.
+
+       * gdk/gdkdraw.c: Use _gdk_gc_update_context() to add support
+       for tiles/stipples/clipping to gdk_draw_glyphs(), 
+       gdk_draw_trapezoids().
+
+       * gdk/gdkpango.c: Use _gdk_gc_update_context() instead of internal
+       implementation of stipples. Use one cairo_t across the entire
+       drawing operation. Replace cairo_matrix_create() with 
+       stack-allocated matrices.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c 
+       gdk/win32/gdkgc-win32.c: Save various aspects of the 
+       GC state (fill, tile, stipple, foreground, background, clip region)
+       in instance-private-data for future use. Add getters.
+       Get rid of _gdk_windowing_gc_get_foreground() function implemented 
+       by the backends.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
+       gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Add
+       _gdk_gc_init() to do initial setup of the GC from values;
+       fixes some problems from drawable redirection.
+
+       * gdk/gdkgc.c gdk/gdkinternals.h gdk/x11/gdkgc-x11.c
+       gdk/win32/gdkgc-win32.c gdk/linux-fb/gdkgc-fb.c: Move 
+       gdk_gc_copy() and gdk_gc_set_clip_{region,rectangle}() into 
+       the generic code, add _gdk_windowing_gc_copy(), 
+       _gdk_windowing_gc_set_clip_region() to do backend specific
+       stuff.
+
+       * gdk/x11/{gdkprivate-x11.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
+       gdk/win32/{gdkprivate-win32.h,gdkgc-x11.c.c,gdkdrawable-x11.c}
+       gdk/linux-fb/{gdkprivate-fb.h,gdkgc-fb.c.c,gdkdrawable-fb.c}:
+       Don't duplicate state that now is stored by the generic code.
+
+       * gdk/gdk.symbols Update
+
 2005-05-02  Matthias Clasen  <mclasen@redhat.com>
 
        * tests/testiconview.c: Test cell renderers.
index b5904f0960bb724a91e236bcbf86fa1ffd1c6367..a7883569becd44ed019b9a8f9e745cea9e52404f 100644 (file)
@@ -579,11 +579,14 @@ gdk_gc_set_stipple
 gdk_gc_set_ts_origin
 gdk_gc_set_clip_origin
 gdk_gc_set_clip_mask
+gdk_gc_set_clip_rectangle
+gdk_gc_set_clip_region
 gdk_gc_set_subwindow
 gdk_gc_set_exposures
 gdk_gc_set_line_attributes
 gdk_gc_set_dashes
 gdk_gc_offset
+gdk_gc_copy
 gdk_gc_get_colormap
 gdk_gc_set_colormap
 gdk_gc_set_rgb_bg_color
@@ -593,10 +596,7 @@ gdk_gc_set_rgb_fg_color
 
 #if IN_HEADER(__GDK_GC_H__)
 #if IN_FILE(__GDK_GC_X11_C__)
-gdk_gc_copy
 gdk_gc_get_screen
-gdk_gc_set_clip_rectangle
-gdk_gc_set_clip_region
 #endif
 #endif
 
index c5bd2d8b629fc6c05c1b7118efde58ca1eff7afb..ca0950d2c4635a7df87e52c5597a209ce458ee3d 100644 (file)
@@ -877,13 +877,10 @@ real_draw_glyphs (GdkDrawable      *drawable,
                  gdouble           y,
                  PangoGlyphString *glyphs)
 {
-  GdkColor color;
   cairo_t *cr;
 
   cr = gdk_drawable_create_cairo_context (drawable);
-  
-  _gdk_windowing_gc_get_foreground (gc, &color);
-  gdk_cairo_set_source_color (cr, &color);
+  _gdk_gc_update_context (gc, cr, NULL, NULL);
 
   if (matrix)
     {
@@ -999,7 +996,6 @@ gdk_draw_trapezoids (GdkDrawable    *drawable,
                     GdkTrapezoid   *trapezoids,
                     gint            n_trapezoids)
 {
-  GdkColor color;
   cairo_t *cr;
   int i;
 
@@ -1008,10 +1004,8 @@ gdk_draw_trapezoids (GdkDrawable    *drawable,
   g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
 
   cr = gdk_drawable_create_cairo_context (drawable);
+  _gdk_gc_update_context (gc, cr, NULL, NULL);
   
-  _gdk_windowing_gc_get_foreground (gc, &color);
-  gdk_cairo_set_source_color (cr, &color);
-
   for (i = 0; i < n_trapezoids; i++)
     {
       cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1);
index c51b4333830ca8e9526d03b9dc534c7eda86b0f1..50179d4110322a66e665e18e6fc7ea7b040f7815 100644 (file)
 #include <string.h>
 
 #include "gdkgc.h"
+#include "gdkinternals.h"
+#include "gdkpixmap.h"
+#include "gdkregion-generic.h"
 #include "gdkrgb.h"
 #include "gdkprivate.h"
 #include "gdkalias.h"
 
-static void gdk_gc_class_init (GObjectClass *class);
 static void gdk_gc_finalize   (GObject      *object);
 
-static GObjectClass *parent_class;
+typedef struct _GdkGCPrivate GdkGCPrivate;
 
-GType
-gdk_gc_get_type (void)
+struct _GdkGCPrivate
 {
-  static GType object_type = 0;
+  GdkRegion *clip_region;
 
-  if (!object_type)
-    {
-      static const GTypeInfo object_info =
-      {
-        sizeof (GdkGCClass),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gdk_gc_class_init,
-        NULL,           /* class_finalize */
-        NULL,           /* class_data */
-        sizeof (GdkGC),
-        0,              /* n_preallocs */
-        (GInstanceInitFunc) NULL,
-      };
-      
-      object_type = g_type_register_static (G_TYPE_OBJECT,
-                                            "GdkGC",
-                                            &object_info, 
-                                           G_TYPE_FLAG_ABSTRACT);
-    }
+  GdkFill fill;
+  GdkBitmap *stipple;
+  GdkPixmap *tile;
   
-  return object_type;
-}
+  guint32 fg_pixel;
+  guint32 bg_pixel;
+};
+
+#define GDK_GC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_GC, GdkGCPrivate))
+
+G_DEFINE_TYPE (GdkGC, gdk_gc, G_TYPE_OBJECT);
 
 static void
-gdk_gc_class_init (GObjectClass *class)
+gdk_gc_class_init (GdkGCClass *class)
 {
-  parent_class = g_type_class_peek_parent (class);
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
   
-  class->finalize = gdk_gc_finalize;
+  object_class->finalize = gdk_gc_finalize;
+
+  g_type_class_add_private (object_class, sizeof (GdkGCPrivate));
 }
 
+static void
+gdk_gc_init (GdkGC *gc)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  priv->fill = GDK_SOLID;
+
+  /* These are the default X11 value, which we match. They are clearly
+   * wrong for TrueColor displays, so apps have to change them.
+   */
+  priv->fg_pixel = 0;
+  priv->bg_pixel = 1;
+}
 
 /**
  * gdk_gc_new:
@@ -109,17 +113,39 @@ gdk_gc_new_with_values (GdkDrawable       *drawable,
                        GdkGCValues     *values,
                        GdkGCValuesMask  values_mask)
 {
-  GdkGC *gc;
-
   g_return_val_if_fail (drawable != NULL, NULL);
 
-  gc = GDK_DRAWABLE_GET_CLASS (drawable)->create_gc (drawable,
-                                                     values,
-                                                     values_mask);
+  return GDK_DRAWABLE_GET_CLASS (drawable)->create_gc (drawable,
+                                                      values,
+                                                      values_mask);
+}
+
+/**
+ * _gdk_gc_init:
+ * @gc: a #GdkGC
+ * @drawable: a #GdkDrawable.
+ * @values: a structure containing initial values for the GC.
+ * @values_mask: a bit mask indicating which fields in @values
+ *   are set.
+ * 
+ * Does initialization of the generic portions of a #GdkGC
+ * created with the specified values and values_mask. This
+ * should be called out of the implementation of
+ * GdkDrawable.create_gc() immediately after creating the
+ * #GdkGC object.
+ **/
+void
+_gdk_gc_init (GdkGC           *gc,
+             GdkDrawable     *drawable,
+             GdkGCValues     *values,
+             GdkGCValuesMask  values_mask)
+{
+  GdkGCPrivate *priv;
+
+  g_return_if_fail (GDK_IS_GC (gc));
+
+  priv = GDK_GC_GET_PRIVATE (gc);
 
-  if (gc == NULL) /* This would mean the drawable was destroyed. */
-    return NULL;
-  
   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
     gc->clip_x_origin = values->clip_x_origin;
   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
@@ -128,29 +154,42 @@ gdk_gc_new_with_values (GdkDrawable       *drawable,
     gc->ts_x_origin = values->ts_x_origin;
   if (values_mask & GDK_GC_TS_Y_ORIGIN)
     gc->ts_y_origin = values->ts_y_origin;
-
-  /* gc->colormap will already be set if gdk_gc_new_with_values()
-   * recurses - as in GdkPixmap => impl object.
-   */
-  if (!gc->colormap)
+  if (values_mask & GDK_GC_FILL)
+    priv->fill = values->fill;
+  if (values_mask & GDK_GC_STIPPLE)
     {
-      gc->colormap = gdk_drawable_get_colormap (drawable);
-      if (gc->colormap)
-       g_object_ref (gc->colormap);
+      priv->stipple = values->stipple;
+      if (priv->stipple)
+       g_object_ref (priv->stipple);
     }
-  
-  return gc;
+  if (values_mask & GDK_GC_TILE)
+    {
+      priv->tile = values->tile;
+      if (priv->tile)
+       g_object_ref (priv->tile);
+    }
+  if (values_mask & GDK_GC_FOREGROUND)
+    priv->fg_pixel = values->foreground.pixel;
+  if (values_mask & GDK_GC_BACKGROUND)
+    priv->bg_pixel = values->background.pixel;
+
+  gc->colormap = gdk_drawable_get_colormap (drawable);
+  if (gc->colormap)
+    g_object_ref (gc->colormap);
 }
 
 static void
 gdk_gc_finalize (GObject *object)
 {
   GdkGC *gc = GDK_GC (object);
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
   
+  if (priv->clip_region)
+    gdk_region_destroy (priv->clip_region);
   if (gc->colormap)
     g_object_unref (gc->colormap);
 
-  parent_class->finalize (object);
+  G_OBJECT_CLASS (gdk_gc_parent_class)->finalize (object);
 }
 
 /**
@@ -219,9 +258,13 @@ gdk_gc_set_values (GdkGC           *gc,
                   GdkGCValues     *values,
                   GdkGCValuesMask  values_mask)
 {
+  GdkGCPrivate *priv;
+
   g_return_if_fail (GDK_IS_GC (gc));
   g_return_if_fail (values != NULL);
 
+  priv = GDK_GC_GET_PRIVATE (gc);
+
   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
     gc->clip_x_origin = values->clip_x_origin;
   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
@@ -230,6 +273,43 @@ gdk_gc_set_values (GdkGC           *gc,
     gc->ts_x_origin = values->ts_x_origin;
   if (values_mask & GDK_GC_TS_Y_ORIGIN)
     gc->ts_y_origin = values->ts_y_origin;
+  if (values_mask & GDK_GC_CLIP_MASK)
+    {
+      GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+      if (priv->clip_region)
+       {
+         gdk_region_destroy (priv->clip_region);
+         priv->clip_region = NULL;
+       }
+    }
+  if (values_mask & GDK_GC_FILL)
+    priv->fill = values->fill;
+  if (values_mask & GDK_GC_STIPPLE)
+    {
+      if (priv->stipple != values->stipple)
+       {
+         if (priv->stipple)
+           g_object_unref (priv->stipple);
+         priv->stipple = values->stipple;
+         if (priv->stipple)
+           g_object_ref (priv->stipple);
+       }
+    }
+  if (values_mask & GDK_GC_TILE)
+    {
+      if (priv->tile != values->tile)
+       {
+         if (priv->tile)
+           g_object_unref (priv->tile);
+         priv->tile = values->tile;
+         if (priv->tile)
+           g_object_ref (priv->tile);
+       }
+    }
+  if (values_mask & GDK_GC_FOREGROUND)
+    priv->fg_pixel = values->foreground.pixel;
+  if (values_mask & GDK_GC_BACKGROUND)
+    priv->bg_pixel = values->background.pixel;
   
   GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
 }
@@ -459,6 +539,169 @@ gdk_gc_set_clip_mask (GdkGC       *gc,
   gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
 }
 
+static void
+_gdk_gc_set_clip_region_internal (GdkGC     *gc,
+                                 GdkRegion *region)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  if (priv->clip_region)
+    gdk_region_destroy (priv->clip_region);
+
+  priv->clip_region = region;
+
+  _gdk_windowing_gc_set_clip_region (gc, region);
+}
+
+/**
+ * gdk_gc_set_clip_rectangle:
+ * @gc: a #GdkGC.
+ * @rectangle: the rectangle to clip to.
+ * 
+ * Sets the clip mask for a graphics context from a
+ * rectangle. The clip mask is interpreted relative to the clip
+ * origin. (See gdk_gc_set_clip_origin()).
+ **/
+void
+gdk_gc_set_clip_rectangle (GdkGC       *gc,
+                          GdkRectangle *rectangle)
+{
+  GdkRegion *region;
+  
+  g_return_if_fail (GDK_IS_GC (gc));
+
+  if (rectangle)
+    region = gdk_region_rectangle (rectangle);
+  else
+    region = NULL;
+
+  _gdk_gc_set_clip_region_internal (gc, region);
+}
+
+/**
+ * gdk_gc_set_clip_region:
+ * @gc: a #GdkGC.
+ * @region: the #GdkRegion. 
+ * 
+ * Sets the clip mask for a graphics context from a region structure.
+ * The clip mask is interpreted relative to the clip origin. (See
+ * gdk_gc_set_clip_origin()).
+ **/
+void
+gdk_gc_set_clip_region (GdkGC    *gc,
+                       GdkRegion *region)
+{
+  g_return_if_fail (GDK_IS_GC (gc));
+
+  if (region)
+    region = gdk_region_copy (region);
+  
+  _gdk_gc_set_clip_region_internal (gc, region);
+}
+
+/**
+ * _gdk_gc_get_clip_region:
+ * @gc: a #GdkGC
+ * 
+ * Gets the current clip region for @gc, if any.
+ * 
+ * Return value: the clip region for the GC, or %NULL.
+ *   (if a clip mask is set, the return will be %NULL)
+ *   This value is owned by the GC and must not be freed.
+ **/
+GdkRegion *
+_gdk_gc_get_clip_region (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), NULL);
+
+  return GDK_GC_GET_PRIVATE (gc)->clip_region;
+}
+
+/**
+ * _gdk_gc_get_fill:
+ * @gc: a #GdkGC
+ * 
+ * Gets the current file style for the GC
+ * 
+ * Return value: the file style for the GC
+ **/
+GdkFill
+_gdk_gc_get_fill (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), GDK_SOLID);
+
+  return GDK_GC_GET_PRIVATE (gc)->fill;
+}
+
+/**
+ * _gdk_gc_get_tile:
+ * @gc: a #GdkGC
+ * 
+ * Gets the tile pixmap for @gc, if any
+ * 
+ * Return value: the tile set on the GC, or %NULL. The
+ *   value is owned by the GC and must not be freed.
+ **/
+GdkPixmap *
+_gdk_gc_get_tile (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), NULL);
+
+  return GDK_GC_GET_PRIVATE (gc)->tile;
+}
+
+/**
+ * _gdk_gc_get_stipple:
+ * @gc: a #GdkGC
+ * 
+ * Gets the stipple pixmap for @gc, if any
+ * 
+ * Return value: the stipple set on the GC, or %NULL. The
+ *   value is owned by the GC and must not be freed.
+ **/
+GdkBitmap *
+_gdk_gc_get_stipple (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), NULL);
+
+  return GDK_GC_GET_PRIVATE (gc)->stipple;
+}
+
+/**
+ * _gdk_gc_get_fg_pixel:
+ * @gc: a #GdkGC
+ * 
+ * Gets the foreground pixel value for @gc. If the
+ * foreground pixel has never been set, returns the
+ * default value 0.
+ * 
+ * Return value: the foreground pixel value of the GC
+ **/
+guint32
+_gdk_gc_get_fg_pixel (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), 0);
+  
+  return GDK_GC_GET_PRIVATE (gc)->fg_pixel;
+}
+
+/**
+ * _gdk_gc_get_bg_pixel:
+ * @gc: a #GdkGC
+ * 
+ * Gets the background pixel value for @gc.If the
+ * foreground pixel has never been set, returns the
+ * default value 1.
+ * 
+ * Return value: the foreground pixel value of the GC
+ **/
+guint32
+_gdk_gc_get_bg_pixel (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), 0);
+  
+  return GDK_GC_GET_PRIVATE (gc)->bg_pixel;
+}
 
 /**
  * gdk_gc_set_subwindow:
@@ -598,6 +841,67 @@ gdk_gc_offset (GdkGC *gc,
     }
 }
 
+/**
+ * gdk_gc_copy:
+ * @dst_gc: the destination graphics context.
+ * @src_gc: the source graphics context.
+ * 
+ * Copy the set of values from one graphics context
+ * onto another graphics context.
+ **/
+void
+gdk_gc_copy (GdkGC *dst_gc,
+            GdkGC *src_gc)
+{
+  GdkGCPrivate *dst_priv, *src_priv;
+  
+  g_return_if_fail (GDK_IS_GC (dst_gc));
+  g_return_if_fail (GDK_IS_GC (src_gc));
+
+  dst_priv = GDK_GC_GET_PRIVATE (dst_gc);
+  src_priv = GDK_GC_GET_PRIVATE (src_gc);
+
+  _gdk_windowing_gc_copy (dst_gc, src_gc);
+
+  dst_gc->clip_x_origin = src_gc->clip_x_origin;
+  dst_gc->clip_y_origin = src_gc->clip_y_origin;
+  dst_gc->ts_x_origin = src_gc->ts_x_origin;
+  dst_gc->ts_y_origin = src_gc->ts_y_origin;
+
+  if (src_gc->colormap)
+    g_object_ref (src_gc->colormap);
+
+  if (dst_gc->colormap)
+    g_object_unref (dst_gc->colormap);
+
+  dst_gc->colormap = src_gc->colormap;
+
+  if (dst_priv->clip_region)
+    gdk_region_destroy (dst_priv->clip_region);
+
+  if (src_priv->clip_region)
+    dst_priv->clip_region = gdk_region_copy (src_priv->clip_region);
+  else
+    dst_priv->clip_region = NULL;
+  
+  dst_priv->fill = src_priv->fill;
+  
+  if (dst_priv->stipple)
+    g_object_unref (dst_priv->stipple);
+  dst_priv->stipple = src_priv->stipple;
+  if (dst_priv->stipple)
+    g_object_ref (dst_priv->stipple);
+  
+  if (dst_priv->tile)
+    g_object_unref (dst_priv->tile);
+  dst_priv->tile = src_priv->tile;
+  if (dst_priv->tile)
+    g_object_ref (dst_priv->tile);
+
+  dst_priv->fg_pixel = src_priv->fg_pixel;
+  dst_priv->bg_pixel = src_priv->bg_pixel;
+}
+
 /**
  * gdk_gc_set_colormap:
  * @gc: a #GdkGC
@@ -724,5 +1028,225 @@ gdk_gc_set_rgb_bg_color (GdkGC          *gc,
   gdk_gc_set_background (gc, &tmp_color);
 }
 
+static cairo_surface_t *
+make_stipple_tile_surface (cairo_t   *cr,
+                          GdkBitmap *stipple,
+                          GdkColor  *foreground,
+                          GdkColor  *background)
+{
+  cairo_t *tmp_cr;
+  cairo_surface_t *surface; 
+  cairo_surface_t *alpha_surface;
+  gint width, height;
+
+  gdk_drawable_get_size (stipple,
+                        &width, &height);
+  
+  alpha_surface = _gdk_drawable_ref_cairo_surface (stipple);
+  
+  surface = cairo_surface_create_similar (cairo_get_target_surface (cr),
+                                         CAIRO_FORMAT_ARGB32,
+                                         width, height);
+
+  tmp_cr = cairo_create ();
+  cairo_set_target_surface (tmp_cr, surface);
+  
+  cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SRC);
+  if (background)
+      gdk_cairo_set_source_color (tmp_cr, background);
+  else
+      cairo_set_source_rgba (tmp_cr, 0, 0, 0 ,0);
+
+  cairo_paint (tmp_cr);
+
+  cairo_set_operator (tmp_cr, CAIRO_OPERATOR_OVER);
+
+  gdk_cairo_set_source_color (tmp_cr, foreground);
+  cairo_mask_surface (tmp_cr, alpha_surface, 0, 0);
+  
+  cairo_destroy (tmp_cr);
+  cairo_surface_destroy (alpha_surface);
+
+  return surface;
+}
+
+static void
+gc_get_foreground (GdkGC    *gc,
+                  GdkColor *color)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+  
+  color->pixel = priv->bg_pixel;
+
+  if (gc->colormap)
+    gdk_colormap_query_color (gc->colormap, priv->bg_pixel, color);
+  else
+    g_warning ("No colormap in gc_get_background");
+}
+
+static void
+gc_get_background (GdkGC    *gc,
+                  GdkColor *color)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+  
+  color->pixel = priv->bg_pixel;
+
+  if (gc->colormap)
+    gdk_colormap_query_color (gc->colormap, priv->bg_pixel, color);
+  else
+    g_warning ("No colormap in gc_get_background");
+}
+
+/**
+ * _gdk_gc_update_context:
+ * @gc: a #GdkGC
+ * @cr: a #cairo_t
+ * @override_foreground: a foreground color to use to override the
+ *   foreground color of the GC
+ * @override_stipple: a stipple pattern to use to override the
+ *   stipple from the GC. If this is present and the fill mode
+ *   of the GC isn't %GDK_STIPPLED or %GDK_OPAQUE_STIPPLED
+ *   the fill mode will be forced to %GDK_STIPPLED
+ * 
+ * Set the attributes of a cairo context to match those of a #GdkGC
+ * as far as possible. Some aspects of a #GdkGC, such as clip masks
+ * and functions other than %GDK_COPY are not currently handled.
+ **/
+void
+_gdk_gc_update_context (GdkGC     *gc,
+                       cairo_t   *cr,
+                       GdkColor  *override_foreground,
+                       GdkBitmap *override_stipple)
+{
+  GdkGCPrivate *priv;
+  GdkFill fill;
+  GdkColor foreground;
+  GdkColor background;
+  cairo_surface_t *tile_surface = NULL;
+  GdkBitmap *stipple = NULL;
+
+  g_return_if_fail (GDK_IS_GC (gc));
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (override_stipple == NULL || GDK_IS_PIXMAP (override_stipple));
+
+  priv = GDK_GC_GET_PRIVATE (gc);
+
+  fill = priv->fill;
+  if (override_stipple && fill != GDK_OPAQUE_STIPPLED)
+    fill = GDK_STIPPLED;
+
+  if (fill != GDK_TILED)
+    {
+      if (override_foreground)
+       foreground = *override_foreground;
+      else
+       gc_get_foreground (gc, &foreground);
+    }
+
+  if (fill == GDK_OPAQUE_STIPPLED)
+    {
+      if (override_foreground)
+       foreground = *override_foreground;
+      else
+       gc_get_background (gc, &background);
+    }
+
+  switch (fill)
+    {
+    case GDK_SOLID:
+      break;
+    case GDK_TILED:
+      if (!priv->tile)
+       fill = GDK_SOLID;
+      break;
+    case GDK_STIPPLED:
+    case GDK_OPAQUE_STIPPLED:
+      if (override_stipple)
+       stipple = override_stipple;
+      else
+       stipple = priv->stipple;
+      
+      if (!stipple)
+       fill = GDK_SOLID;
+      break;
+    }
+  
+  switch (fill)
+    {
+    case GDK_SOLID:
+      gdk_cairo_set_source_color (cr, &foreground);
+      break;
+    case GDK_TILED:
+      tile_surface = _gdk_drawable_ref_cairo_surface (priv->tile);
+      break;
+    case GDK_STIPPLED:
+      tile_surface = make_stipple_tile_surface (cr, stipple, &foreground, NULL);
+      break;
+    case GDK_OPAQUE_STIPPLED:
+      tile_surface = make_stipple_tile_surface (cr, stipple, &foreground, &background);
+      break;
+    }
+
+  /* Tiles, stipples, and clip regions are all specified in device space,
+   * not user space. For the clip region, we can simply change the matrix,
+   * clip, then clip back, but for the source pattern, we need to
+   * compute the right matrix.
+   *
+   * What we want is:
+   *
+   *     CTM_inverse * Pattern_matrix = Translate(- ts_x, - ts_y)
+   *
+   * (So that ts_x, ts_y in device space is taken to 0,0 in pattern
+   * space). So, pattern_matrix = CTM * Translate(- ts_x, - tx_y);
+   */
+
+  if (tile_surface)
+    {
+      cairo_pattern_t *pattern = cairo_pattern_create_for_surface (tile_surface);
+      cairo_matrix_t user_to_device;
+      cairo_matrix_t user_to_pattern;
+      cairo_matrix_t device_to_pattern;
+
+      cairo_get_matrix (cr, &user_to_device);
+      cairo_matrix_init_translate (&device_to_pattern,
+                                  - gc->ts_x_origin, - gc->ts_y_origin);
+      cairo_matrix_multiply (&user_to_pattern,
+                            &user_to_device, &device_to_pattern);
+      
+      cairo_pattern_set_matrix (pattern, &user_to_pattern);
+      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+      cairo_set_source (cr, pattern);
+      
+      cairo_surface_destroy (tile_surface);
+      cairo_pattern_destroy (pattern);
+    }
+
+  cairo_reset_clip (cr);
+  if (priv->clip_region)
+    {
+      GdkRegionBox *boxes = priv->clip_region->rects;
+      gint n_boxes = priv->clip_region->numRects;
+      int i;
+
+      cairo_save (cr);
+
+      cairo_identity_matrix (cr);
+      
+      cairo_new_path (cr);
+      for (i=0; i < n_boxes; i++)
+       cairo_rectangle (cr,
+                        boxes[i].x1 + gc->clip_x_origin,
+                        boxes[i].y1 + gc->clip_y_origin,
+                        boxes[i].x2 - boxes[i].x1,
+                        boxes[i].y2 - boxes[i].y1);
+
+      cairo_restore (cr);
+
+      cairo_clip (cr);
+    }
+}
+
 #define __GDK_GC_C__
 #include "gdkaliasdef.c"
index ffe770017f35f9b930151c34204f8e776d4edd5a..c5aaca8aafad468e55a210080796f9d208a4fb42 100644 (file)
@@ -216,6 +216,11 @@ cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable);
 GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
                                     gboolean     graphics_exposures);
 
+void _gdk_gc_update_context (GdkGC     *gc,
+                            cairo_t   *cr,
+                            GdkColor  *override_foreground,
+                            GdkBitmap *override_stipple);
+
 /*************************************
  * Interfaces used by windowing code *
  *************************************/
@@ -228,6 +233,18 @@ void       _gdk_screen_close             (GdkScreen   *screen);
 
 const char *_gdk_get_sm_client_id (void);
 
+void _gdk_gc_init (GdkGC           *gc,
+                  GdkDrawable     *drawable,
+                  GdkGCValues     *values,
+                  GdkGCValuesMask  values_mask);
+
+GdkRegion *_gdk_gc_get_clip_region (GdkGC *gc);
+GdkFill    _gdk_gc_get_fill        (GdkGC *gc);
+GdkPixmap *_gdk_gc_get_tile        (GdkGC *gc);
+GdkBitmap *_gdk_gc_get_stipple     (GdkGC *gc);
+guint32    _gdk_gc_get_fg_pixel    (GdkGC *gc);
+guint32    _gdk_gc_get_bg_pixel    (GdkGC *gc);
+
 /*****************************************
  * Interfaces provided by windowing code *
  *****************************************/
@@ -323,9 +340,41 @@ GType _gdk_window_impl_get_type (void) G_GNUC_CONST;
 GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
 
 
+/**
+ * _gdk_windowing_gc_set_clip_region:
+ * @gc: a #GdkGC
+ * @region: the new clip region
+ * 
+ * Do any window-system specific processing necessary
+ * for a change in clip region. Since the clip origin
+ * will likely change before the GC is used with the
+ * new clip, frequently this function will only set a flag and
+ * do the real processing later.
+ *
+ * When this function is called, _gdk_gc_get_clip_region
+ * will already return the new region.
+ **/
+void _gdk_windowing_gc_set_clip_region (GdkGC     *gc,
+                                       GdkRegion *region);
+
+/**
+ * _gdk_windowing_gc_copy:
+ * @dst_gc: a #GdkGC from the GDK backend
+ * @src_gc: a #GdkGC from the GDK backend
+ * 
+ * Copies backend specific state from @src_gc to @dst_gc.
+ * This is called before the generic state is copied, so
+ * the old generic state is still available from @dst_gc
+ **/
+void _gdk_windowing_gc_copy (GdkGC *dst_gc,
+                            GdkGC *src_gc);
+     
 /* Queries the current foreground color of a GdkGC */
 void _gdk_windowing_gc_get_foreground (GdkGC    *gc,
                                       GdkColor *color);
+/* Queries the current background color of a GdkGC */
+void _gdk_windowing_gc_get_background (GdkGC    *gc,
+                                      GdkColor *color);
 
 /************************************
  * Initialization and exit routines *
index bf5b517cf2411dd33d1f3962820066932b4eff73..a5801fcbfed488becc0fc1c055a559885447b2e7 100644 (file)
@@ -49,9 +49,11 @@ struct _GdkPangoRendererPrivate
   gboolean override_color_set[MAX_RENDER_PART + 1];
   
   GdkBitmap *stipple[MAX_RENDER_PART + 1];
-  cairo_surface_t *stipple_surface[MAX_RENDER_PART + 1];
   gboolean embossed;
 
+  cairo_t *cr;
+  PangoRenderPart last_part;
+
   /* Current target */
   GdkDrawable *drawable;
   GdkGC *base_gc;
@@ -79,10 +81,6 @@ gdk_pango_renderer_finalize (GObject *object)
   if (priv->drawable)
     g_object_unref (priv->drawable);
 
-  for (i = 0; i <= MAX_RENDER_PART; i++)
-    if (priv->stipple_surface[i])
-      cairo_surface_destroy (priv->stipple_surface[i]);
-
   for (i = 0; i <= MAX_RENDER_PART; i++)
     if (priv->stipple[i])
       g_object_unref (priv->stipple[i]);
@@ -132,122 +130,56 @@ emboss_context (cairo_t *cr)
   cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
 }
 
-static void
-set_part_color (GdkPangoRenderer *gdk_renderer,
-               cairo_t          *cr,
-               PangoRenderPart   part)
-{
-  PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (gdk_renderer),
-                                               part);
-  if (color)
-    {
-      cairo_set_source_rgb (cr,
-                           color->red / 65535.,
-                           color->green / 65535.,
-                           color->blue / 65535.);
-    }
-  else
-    {
-      GdkColor gc_color;
-      
-      _gdk_windowing_gc_get_foreground (gdk_renderer->priv->base_gc, &gc_color);
-      gdk_cairo_set_source_color (cr, &gc_color);
-    }
-}
-
-static cairo_surface_t *
-get_stipple_surface (GdkPangoRenderer *gdk_renderer,
-                    cairo_t          *cr,
-                    PangoRenderPart   part)
-{
-  if (!gdk_renderer->priv->stipple_surface[part])
-    {
-      cairo_t *tmp_cr;
-      cairo_surface_t *surface; 
-      cairo_surface_t *alpha_surface;
-      gint width, height;
-
-      gdk_drawable_get_size (gdk_renderer->priv->stipple[part],
-                            &width, &height);
-
-      alpha_surface = _gdk_drawable_ref_cairo_surface (gdk_renderer->priv->stipple[part]);
-
-      surface = cairo_surface_create_similar (cairo_get_target_surface (cr),
-                                             CAIRO_FORMAT_ARGB32,
-                                             width, height);
-
-      tmp_cr = cairo_create ();
-      cairo_set_target_surface (tmp_cr, surface);
-
-      cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SRC);
-      cairo_show_surface (tmp_cr, alpha_surface, width, height);
-
-      set_part_color (gdk_renderer, tmp_cr, part);
-      cairo_set_operator (tmp_cr, CAIRO_OPERATOR_ATOP);
-      
-      cairo_rectangle (tmp_cr, 0, 0, width, height);
-      cairo_fill (tmp_cr);
-
-      cairo_destroy (tmp_cr);
-      cairo_surface_destroy (alpha_surface);
-
-      gdk_renderer->priv->stipple_surface[part] = surface;
-    }
-
-  return gdk_renderer->priv->stipple_surface[part];
-}
-
 static cairo_t *
-create_cairo_context (GdkPangoRenderer *gdk_renderer,
-                     PangoRenderPart   part)
+get_cairo_context (GdkPangoRenderer *gdk_renderer,
+                  PangoRenderPart   part)
 {
   PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer);
-  const PangoMatrix *matrix;
-  cairo_t *cr = gdk_drawable_create_cairo_context (gdk_renderer->priv->drawable);
+  GdkPangoRendererPrivate *priv = gdk_renderer->priv;
 
-  if (gdk_renderer->priv->stipple[part])
+  if (!priv->cr)
     {
-      cairo_surface_t *surface = get_stipple_surface (gdk_renderer, cr, part);
-      cairo_pattern_t *pattern;
-
-      pattern = cairo_pattern_create_for_surface (surface);
-      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+      const PangoMatrix *matrix;
+      
+      priv->cr = gdk_drawable_create_cairo_context (priv->drawable);
 
-      if (gdk_renderer->priv->base_gc->ts_x_origin != 0 ||
-         gdk_renderer->priv->base_gc->ts_y_origin != 0)
+      matrix = pango_renderer_get_matrix (renderer);
+      if (matrix)
        {
-         cairo_matrix_t *matrix = cairo_matrix_create ();
-         cairo_matrix_translate (matrix,
-                                 - gdk_renderer->priv->base_gc->ts_x_origin,
-                                 - gdk_renderer->priv->base_gc->ts_y_origin);
-         cairo_pattern_set_matrix (pattern, matrix);
-         cairo_matrix_destroy (matrix);
+         cairo_matrix_t cairo_matrix;
+         
+         cairo_matrix_init (&cairo_matrix,
+                            matrix->xx, matrix->yx,
+                            matrix->xy, matrix->yy,
+                            matrix->x0, matrix->y0);
+         cairo_set_matrix (priv->cr, &cairo_matrix);
        }
-
-      cairo_set_source (cr, pattern);
-      cairo_pattern_destroy (pattern);
     }
-  else
-    {
-      set_part_color (gdk_renderer, cr, part);
-    }
-
-  matrix = pango_renderer_get_matrix (renderer);
-  if (matrix)
+  
+  priv->last_part = (PangoRenderPart)-1;
+  if (part != priv->last_part)
     {
-      cairo_matrix_t *cairo_matrix;
+      PangoColor *pango_color = pango_renderer_get_color (renderer,
+                                                         part);
+      GdkColor *color = NULL;
+      GdkColor tmp_color;
+      if (pango_color)
+       {
+         tmp_color.red = pango_color->red;
+         tmp_color.green = pango_color->green;
+         tmp_color.blue = pango_color->blue;
+         
+         color = &tmp_color;
+       }
 
-      cairo_matrix = cairo_matrix_create ();
-      cairo_matrix_set_affine (cairo_matrix,
-                              matrix->xx, matrix->yx,
-                              matrix->xy, matrix->yy,
-                              matrix->x0, matrix->y0);
-      
-      cairo_set_matrix (cr, cairo_matrix);
-      cairo_matrix_destroy (cairo_matrix);
+      _gdk_gc_update_context (priv->base_gc,
+                             priv->cr,
+                             color,
+                             priv->stipple[part]);
+      priv->last_part = part;
     }
 
-  return cr;
+  return priv->cr;
 }
 
 static void
@@ -261,8 +193,8 @@ gdk_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
   cairo_t *cr;
 
-  cr = create_cairo_context (gdk_renderer, 
-                            PANGO_RENDER_PART_FOREGROUND);
+  cr = get_cairo_context (gdk_renderer, 
+                         PANGO_RENDER_PART_FOREGROUND);
 
   if (priv->embossed)
     {
@@ -275,8 +207,6 @@ gdk_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
   
   cairo_move_to (cr, x / PANGO_SCALE, y / PANGO_SCALE);
   pango_cairo_show_glyph_string (cr, font, glyphs);
-  
-  cairo_destroy (cr);
 }
 
 /* Draws an error underline that looks like one of:
@@ -369,7 +299,7 @@ gdk_pango_renderer_draw_rectangle (PangoRenderer    *renderer,
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
   cairo_t *cr;
   
-  cr = create_cairo_context (gdk_renderer, part);
+  cr = get_cairo_context (gdk_renderer, part);
 
   if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND)
     {
@@ -387,8 +317,6 @@ gdk_pango_renderer_draw_rectangle (PangoRenderer    *renderer,
                   (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
                   (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
   cairo_fill (cr);
-  
-  cairo_destroy (cr);
 }
 
 static void
@@ -402,7 +330,7 @@ gdk_pango_renderer_draw_error_underline (PangoRenderer    *renderer,
   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
   cairo_t *cr;
   
-  cr = create_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE);
+  cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE);
   
   if (priv->embossed)
     {
@@ -417,8 +345,6 @@ gdk_pango_renderer_draw_error_underline (PangoRenderer    *renderer,
   draw_error_underline (cr,
                        (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
                        (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
-  
-  cairo_destroy (cr);
 }
 
 static void
@@ -427,25 +353,37 @@ gdk_pango_renderer_part_changed (PangoRenderer   *renderer,
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
 
-  if (gdk_renderer->priv->stipple_surface[part])
-    {
-      cairo_surface_destroy (gdk_renderer->priv->stipple_surface[part]);
-      gdk_renderer->priv->stipple_surface[part] = NULL;
-    }
+  if (gdk_renderer->priv->last_part == part)
+    gdk_renderer->priv->last_part = (PangoRenderPart)-1;
 }
 
-void
+static void
 gdk_pango_renderer_begin (PangoRenderer *renderer)
 {
   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
-
-  if (!gdk_renderer->priv->drawable || !gdk_renderer->priv->base_gc)
+  GdkPangoRendererPrivate *priv = gdk_renderer->priv;
+  
+  if (!priv->drawable || !priv->base_gc)
     {
       g_warning ("gdk_pango_renderer_set_drawable() and gdk_pango_renderer_set_drawable()"
                 "must be used to set the target drawable and GC before using the renderer\n");
     }
 }
 
+static void
+gdk_pango_renderer_end (PangoRenderer *renderer)
+{
+  GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
+  GdkPangoRendererPrivate *priv = gdk_renderer->priv;
+
+  if (priv->cr)
+    {
+      cairo_destroy (priv->cr);
+      priv->cr = NULL;
+    }
+  priv->last_part = (PangoRenderPart)-1;
+}
+
 static void
 gdk_pango_renderer_prepare_run (PangoRenderer  *renderer,
                                PangoLayoutRun *run)
@@ -541,6 +479,8 @@ gdk_pango_renderer_init (GdkPangoRenderer *renderer)
   renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer,
                                                GDK_TYPE_PANGO_RENDERER,
                                                GdkPangoRendererPrivate);
+
+  renderer->priv->last_part = (PangoRenderPart)-1;
 }
 
 static void
@@ -555,6 +495,7 @@ gdk_pango_renderer_class_init (GdkPangoRendererClass *klass)
   renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline;
   renderer_class->part_changed = gdk_pango_renderer_part_changed;
   renderer_class->begin = gdk_pango_renderer_begin;
+  renderer_class->end = gdk_pango_renderer_end;
   renderer_class->prepare_run = gdk_pango_renderer_prepare_run;
 
   object_class->finalize = gdk_pango_renderer_finalize;
index 03829181bcde172cf301401d2c976e48872ee267..145e27519413e936488e2ae3ceb31bf463e1887b 100644 (file)
@@ -1800,16 +1800,12 @@ gdk_window_clear_backing_rect (GdkWindow *window,
 
   gdk_window_set_bg_pattern (window, cr, 0, 0);
 
-  cairo_save (cr);
-
   cairo_rectangle (cr, x, y, width, height);
   cairo_clip (cr);
 
   region_path (cr, paint->region);
   cairo_fill (cr);
 
-  cairo_restore (cr);
-
   cairo_destroy (cr);
 }
 
index 20d11053044d71c5a0edc4fb7fbe7870c878d25a..adbb79cee5a7a6dff4c5f9246945e9da419c9e14 100644 (file)
@@ -433,9 +433,11 @@ gdk_fb_clip_region (GdkDrawable *drawable,
 
   if (gc)
     {
-      if (GDK_GC_FBDATA (gc)->clip_region)
+      GdkRegion *gc = _gdk_gc_get_clip_region (gc);
+      
+      if (clip_region)
        {
-         tmpreg = gdk_region_copy (GDK_GC_FBDATA (gc)->clip_region);
+         tmpreg = gdk_region_copy (clip_region);
          gdk_region_offset (tmpreg, private->abs_x + GDK_GC_P (gc)->clip_x_origin,
                             private->abs_y + GDK_GC_P (gc)->clip_y_origin);
          gdk_region_intersect (real_clip_region, tmpreg);
index 8b8a4c702d1d8581d4e80230191e609341c4d65c..a27b9ea9629ff98e7acac65e6c1aced70e28f4d8 100644 (file)
@@ -79,6 +79,8 @@ _gdk_fb_gc_new (GdkDrawable      *drawable,
 
   gc = g_object_new (gdk_gc_fb_get_type (), NULL);
 
+  _gdk_gc_init (gc, drawable, values, values_mask);
+
   private = (GdkGCFBData *)gc;
   
   private->depth = GDK_DRAWABLE_FBDATA (drawable)->depth;
@@ -103,14 +105,8 @@ gdk_fb_gc_finalize (GObject *obj)
 
   private = GDK_GC_FBDATA (gc);
 
-  if (private->clip_region)
-    gdk_region_destroy (private->clip_region);
   if (private->values.clip_mask)
     gdk_pixmap_unref (private->values.clip_mask);
-  if (private->values.stipple)
-    gdk_pixmap_unref (private->values.stipple);
-  if (private->values.tile)
-    gdk_pixmap_unref (private->values.tile);
 
   g_free (private->dash_list);
 
@@ -175,7 +171,7 @@ gdk_fb_gc_set_values (GdkGC           *gc,
       if (values->tile)
        g_assert (GDK_DRAWABLE_IMPL_FBDATA (values->tile)->depth >= 8);
 
-      private->values.tile = values->tile ? gdk_pixmap_ref (values->tile) : NULL;
+      private->values.tile = values->tile;
       private->values_mask |= GDK_GC_TILE;
       if (oldpm)
        gdk_pixmap_unref (oldpm);
@@ -186,7 +182,7 @@ gdk_fb_gc_set_values (GdkGC           *gc,
       oldpm = private->values.stipple;
       if (values->stipple)
        g_assert (GDK_DRAWABLE_IMPL_FBDATA (values->stipple)->depth == 1);
-      private->values.stipple = values->stipple ? gdk_pixmap_ref (values->stipple) : NULL;
+      private->values.stipple = values->stipple;
       private->values_mask |= GDK_GC_STIPPLE;
       if (oldpm)
        gdk_pixmap_unref (oldpm);
@@ -200,12 +196,6 @@ gdk_fb_gc_set_values (GdkGC           *gc,
       private->values_mask |= GDK_GC_CLIP_MASK;
       if (oldpm)
        gdk_pixmap_unref (oldpm);
-
-      if (private->clip_region)
-       {
-         gdk_region_destroy (private->clip_region);
-         private->clip_region = NULL;
-       }
     }
 
   if (values_mask & GDK_GC_SUBWINDOW)
@@ -313,60 +303,13 @@ gc_unset_cmask(GdkGC *gc)
 }
 
 void
-gdk_gc_set_clip_rectangle (GdkGC       *gc,
-                          GdkRectangle *rectangle)
-{
-  GdkGC *private = (GdkGC *)gc;
-  GdkGCFBData *data;
-
-  g_return_if_fail (gc != NULL);
-
-  data = GDK_GC_FBDATA (gc);
-
-  if (data->clip_region)
-    {
-      gdk_region_destroy (data->clip_region);
-      data->clip_region = NULL;
-    }
-
-  if (rectangle)
-    data->clip_region = gdk_region_rectangle (rectangle);
-
-  private->clip_x_origin = 0;
-  private->clip_y_origin = 0;
-  data->values.clip_x_origin = 0;
-  data->values.clip_y_origin = 0;
-
-  gc_unset_cmask (gc);
-
-  _gdk_fb_gc_calc_state (gc, GDK_GC_CLIP_X_ORIGIN|GDK_GC_CLIP_Y_ORIGIN);
-} 
-
-void
-gdk_gc_set_clip_region (GdkGC    *gc,
-                       GdkRegion *region)
+_gdk_windowing_gc_set_clip_region (GdkGC     *gc,
+                                  GdkRegion *region)
 {
-  GdkGC *private = (GdkGC *)gc;
-  GdkGCFBData *data;
-
-  g_return_if_fail (gc != NULL);
-
-  data = GDK_GC_FBDATA (gc);
-
-  if (region == data->clip_region)
-    return;
+  GdkGCFBData *data = GDK_GC_FBDATA (gc);
 
-  if (data->clip_region)
-    {
-      gdk_region_destroy (data->clip_region);
-      data->clip_region = NULL;
-    }
-
-  if (region)
-    data->clip_region = gdk_region_copy (region);
-  
-  private->clip_x_origin = 0;
-  private->clip_y_origin = 0;
+  gc->clip_x_origin = 0;
+  gc->clip_y_origin = 0;
   data->values.clip_x_origin = 0;
   data->values.clip_y_origin = 0;
 
@@ -377,49 +320,35 @@ gdk_gc_set_clip_region (GdkGC       *gc,
 
 
 void
-gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
+_gdk_windowing_gc_copy (GdkGC *dst_gc,
+                       GdkGC *src_gc)
 {
-  GdkGCFBData *dst_private;
-  GdkGCFBData *src_private;
-
-  src_private = GDK_GC_FBDATA (dst_gc);
-  dst_private = GDK_GC_FBDATA (dst_gc);
-
-  g_return_if_fail (dst_gc != NULL);
-  g_return_if_fail (src_gc != NULL);
-
-  if (dst_private->clip_region)
-    gdk_region_destroy (dst_private->clip_region);
+  GdkGCFBData *dst_private = GDK_GC_FBDATA (dst_gc);
+  GdkGCFBData *src_private = GDK_GC_FBDATA (src_gc);
+  GdkGCValuesMask old_mask = dst_private->values_mask;
 
   if (dst_private->values_mask & GDK_GC_FONT)
     gdk_font_unref (dst_private->values.font);
-  if (dst_private->values_mask & GDK_GC_TILE)
-    gdk_pixmap_unref (dst_private->values.tile);
-  if (dst_private->values_mask & GDK_GC_STIPPLE)
-    gdk_pixmap_unref (dst_private->values.stipple);
   if (dst_private->values_mask & GDK_GC_CLIP_MASK)
-    gdk_pixmap_unref (dst_private->values.clip_mask);
+    g_object_unref (dst_private->values.clip_mask);
 
   g_free (dst_private->dash_list);
 
-  *dst_private = *src_private;
+  if (src_private->dash_list)
+    dst_private->dash_list = g_memdup (src_private->dash_list,
+                                      src_private->dash_list_len);
+  
+  dst_private->values_mask = src_private->values_mask;
+  dst_private->values = src_private->values;
   if (dst_private->values_mask & GDK_GC_FONT)
     gdk_font_ref (dst_private->values.font);
-  if (dst_private->values_mask & GDK_GC_TILE)
-    gdk_pixmap_ref (dst_private->values.tile);
-  if (dst_private->values_mask & GDK_GC_STIPPLE)
-    gdk_pixmap_ref (dst_private->values.stipple);
   if (dst_private->values_mask & GDK_GC_CLIP_MASK)
-    gdk_pixmap_ref (dst_private->values.clip_mask);
-  
-  if (dst_private->clip_region)
-    dst_private->clip_region = gdk_region_copy (dst_private->clip_region);
-  
-  if (dst_private->dash_list)
-    {
-      dst_private->dash_list = g_malloc (dst_private->dash_list_len);
-      memcpy (dst_private->dash_list,
-             src_private->dash_list,
-             dst_private->dash_list_len);
-    }
+    g_object_ref (dst_private->values.clip_mask);
+
+  dst_private->dash_offset = src_private->dash_offset;
+  dst_private->alu = src_private->alu;
+
+  dst_private->set_pixel = src_private->set_pixel;
+
+  _gdk_fb_gc_calc_state (gc, old_mask | dst_private->values_mask);
 }
index a64d06edfad4a89173e22c839ffe6c7d84470d2b..4466ffcb721be2dae571b56027fff463be0e18ec 100644 (file)
@@ -229,7 +229,6 @@ typedef void gdk_fb_draw_drawable_func (GdkDrawable *drawable,
 typedef struct {
   GdkGC parent_instance;
 
-  GdkRegion *clip_region;
   gchar *dash_list;
   GdkGCValuesMask values_mask;
   GdkGCValues values;
index cf4412ccd6542bdb7ce9ec1bbed66055711f4b4a..58576ffc2fd93d9d1b66d53756cef796d8cb84d6 100644 (file)
@@ -525,6 +525,7 @@ generic_draw (GdkDrawable    *drawable,
   GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc);
   HDC hdc;
   va_list args;
+  GdkFillStyle *fill_style = _gdk_gc_get_fill (gc);
 
   va_start (args, region);
 
@@ -532,14 +533,14 @@ generic_draw (GdkDrawable    *drawable,
    */
 
   if (gcwin32->values_mask & GDK_GC_FILL &&
-      ((gcwin32->fill_style == GDK_TILED &&
+      ((fill_style == GDK_TILED &&
        gcwin32->values_mask & GDK_GC_TILE &&
-       gcwin32->tile != NULL)
+       _gdk_gc_get_tile (gc) != NULL)
        ||
-       ((gcwin32->fill_style == GDK_OPAQUE_STIPPLED ||
-        gcwin32->fill_style == GDK_STIPPLED) &&
+       ((fill_style == GDK_OPAQUE_STIPPLED ||
+        fill_style == GDK_STIPPLED) &&
        gcwin32->values_mask & GDK_GC_STIPPLE &&
-       gcwin32->stipple != NULL)))
+       _gdk_gc_get_stipple (gc) != NULL)))
     {
       const GdkGCValuesMask blitting_mask = 0;
       GdkGCValuesMask drawing_mask = GDK_GC_FOREGROUND;
@@ -614,11 +615,11 @@ generic_draw (GdkDrawable    *drawable,
                   region->extents.x1, region->extents.y1, args);
       gdk_win32_hdc_release (mask_pixmap, mask_gc, drawing_mask);
 
-      if (gcwin32->fill_style == GDK_TILED)
+      if (fill_style == GDK_TILED)
        {
          /* Tile pixmap with tile */
          draw_tiles (tile_pixmap, tile_gc, SRCCOPY,
-                     gcwin32->tile,
+                     _gdk_gc_get_tile (gc),
                      0, 0, ts_x_origin, ts_y_origin,
                      width, height);
        }
@@ -632,14 +633,14 @@ generic_draw (GdkDrawable    *drawable,
 
          /* Tile stipple bitmap */
          draw_tiles (stipple_bitmap, stipple_gc, SRCCOPY,
-                     gcwin32->stipple,
+                     _gdk_gc_get_stipple (gc),
                      0, 0, ts_x_origin, ts_y_origin,
                      width, height);
 
-         if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
+         if (fill_style == GDK_OPAQUE_STIPPLED)
            {
              /* Fill tile pixmap with background */
-             fg.pixel = gcwin32->background;
+             fg.pixel = _gdk_gc_get_bg_pixel (gc);
              gdk_gc_set_foreground (tile_gc, &fg);
              gdk_draw_rectangle (tile_pixmap, tile_gc, TRUE,
                                  0, 0, width, height);
@@ -658,8 +659,8 @@ generic_draw (GdkDrawable    *drawable,
       if ((old_tile_hbm = SelectObject (tile_hdc, GDK_PIXMAP_HBITMAP (tile_pixmap))) == NULL)
        WIN32_GDI_FAILED ("SelectObject");
 
-      if (gcwin32->fill_style == GDK_STIPPLED ||
-         gcwin32->fill_style == GDK_OPAQUE_STIPPLED)
+      if (fill_style == GDK_STIPPLED ||
+         fill_style == GDK_OPAQUE_STIPPLED)
        {
          HDC stipple_hdc;
          HGDIOBJ old_stipple_hbm;
@@ -676,7 +677,7 @@ generic_draw (GdkDrawable    *drawable,
 
          if ((fg_brush = CreateSolidBrush
               (_gdk_win32_colormap_color (impl->colormap,
-                                          gcwin32->foreground))) == NULL)
+                                          _gdk_gc_get_fg_pixel (gc)))) == NULL)
            WIN32_GDI_FAILED ("CreateSolidBrush");
 
          if ((old_tile_brush = SelectObject (tile_hdc, fg_brush)) == NULL)
@@ -701,7 +702,7 @@ generic_draw (GdkDrawable    *drawable,
          GDI_CALL (BitBlt, (tile_hdc, 0, 0, width, height,
                             stipple_hdc, 0, 0, ROP3_DSPDxax));
 
-         if (gcwin32->fill_style == GDK_STIPPLED)
+         if (fill_style == GDK_STIPPLED)
            {
              /* Punch holes in mask where stipple is zero */
              GDI_CALL (BitBlt, (mask_hdc, 0, 0, width, height,
@@ -1549,8 +1550,8 @@ blit_from_pixmap (gboolean              use_fg_bg,
              
              if (use_fg_bg)
                {
-                 bgix = gcwin32->background;
-                 fgix = gcwin32->foreground;
+                 bgix = _gdk_gc_get_bg_pixel (gc);
+                 fgix = _gdk_gc_get_fg_pixel (gc);
                }
              else
                {
index 787a01354608d11f3a2a4daf18ab386eb0353533..0be44dd7f36f3026c63ea0284a70271b78614f85 100644 (file)
@@ -107,12 +107,6 @@ gdk_gc_win32_finalize (GObject *object)
   if (win32_gc->values_mask & GDK_GC_FONT)
     gdk_font_unref (win32_gc->font);
   
-  if (win32_gc->values_mask & GDK_GC_TILE)
-    g_object_unref (win32_gc->tile);
-  
-  if (win32_gc->values_mask & GDK_GC_STIPPLE)
-    g_object_unref (win32_gc->stipple);
-
   if (win32_gc->pen_dashes)
     g_free (win32_gc->pen_dashes);
   
@@ -125,21 +119,18 @@ gdk_win32_gc_values_to_win32values (GdkGCValues    *values,
                                    GdkGCWin32     *win32_gc)
 {                                  
   char *s = "";
-  gint sw, sh;
 
   GDK_NOTE (GC, g_print ("{"));
 
   if (mask & GDK_GC_FOREGROUND)
     {
-      win32_gc->foreground = values->foreground.pixel;
       win32_gc->values_mask |= GDK_GC_FOREGROUND;
-      GDK_NOTE (GC, (g_print ("fg=%.06lx", win32_gc->foreground),
+      GDK_NOTE (GC, (g_print ("fg=%.06lx", values->,
                     s = ","));
     }
   
   if (mask & GDK_GC_BACKGROUND)
     {
-      win32_gc->background = values->background.pixel;
       win32_gc->values_mask |= GDK_GC_BACKGROUND;
       GDK_NOTE (GC, (g_print ("%sbg=%.06lx", s, win32_gc->background),
                     s = ","));
@@ -196,25 +187,20 @@ gdk_win32_gc_values_to_win32values (GdkGCValues    *values,
 
   if (mask & GDK_GC_FILL)
     {
-      win32_gc->fill_style = values->fill;
       win32_gc->values_mask |= GDK_GC_FILL;
       GDK_NOTE (GC, (g_print ("%sfill=%s", s,
-                             _gdk_win32_fill_style_to_string (win32_gc->fill_style)),
+                             _gdk_win32_fill_style_to_string (values->fill)),
                     s = ","));
     }
 
   if (mask & GDK_GC_TILE)
     {
-      if (win32_gc->tile != NULL)
-       g_object_unref (win32_gc->tile);
-      win32_gc->tile = values->tile;
-      if (win32_gc->tile != NULL)
+      if (values->tile != NULL)
        {
-         g_object_ref (win32_gc->tile);
          win32_gc->values_mask |= GDK_GC_TILE;
          GDK_NOTE (GC,
                    (g_print ("%stile=%p", s,
-                             GDK_PIXMAP_HBITMAP (win32_gc->tile)),
+                             GDK_PIXMAP_HBITMAP (values->tile)),
                     s = ","));
        }
       else
@@ -227,17 +213,19 @@ gdk_win32_gc_values_to_win32values (GdkGCValues    *values,
 
   if (mask & GDK_GC_STIPPLE)
     {
-      if (win32_gc->stipple != NULL)
-       g_object_unref (win32_gc->stipple);
-      win32_gc->stipple = values->stipple;
-      if (win32_gc->stipple != NULL)
+      if (values->stipple != NULL)
        {
-         gdk_drawable_get_size (win32_gc->stipple, &sw, &sh);
-
 #if 0 /* HB: this size limitation is disabled to make radio and check
        * buttons work. I got the impression from the API docs, that
        * it shouldn't be necessary at all, but win9x would do the clipping
+       *
+       * This code will need some work if reenabled since the stipple is
+       * now stored in the backend-independent code.
        */
+          gint sw, sh;
+         
+         gdk_drawable_get_size (values->stipple, &sw, &sh);
+
          if (   (sw != 8 || sh != 8)
              && !G_WIN32_IS_NT_BASED ()) /* HB: the MSDN says it's a Win95 limitation */
            {
@@ -257,7 +245,7 @@ gdk_win32_gc_values_to_win32values (GdkGCValues    *values,
                  j = 0;
                  while (j < 8)
                    {
-                     gdk_draw_drawable (bm, gc, win32_gc->stipple, 0, 0, i, j, sw, sh);
+                     gdk_draw_drawable (bm, gc, values->stipple, 0, 0, i, j, sw, sh);
                      j += sh;
                    }
                  i += sw;
@@ -265,13 +253,11 @@ gdk_win32_gc_values_to_win32values (GdkGCValues    *values,
              win32_gc->stipple = bm;
              gdk_gc_unref (gc);
            }
-         else
 #endif
-           g_object_ref (win32_gc->stipple);
          win32_gc->values_mask |= GDK_GC_STIPPLE;
          GDK_NOTE (GC,
                    (g_print ("%sstipple=%p", s,
-                             GDK_PIXMAP_HBITMAP (win32_gc->stipple)),
+                             GDK_PIXMAP_HBITMAP (values->stipple)),
                     s = ","));
        }
       else
@@ -446,18 +432,12 @@ _gdk_win32_gc_new (GdkDrawable      *drawable,
   gc = g_object_new (_gdk_gc_win32_get_type (), NULL);
   win32_gc = GDK_GC_WIN32 (gc);
 
+  _gdk_gc_init (gc, drawable, values, values_mask);
+
   win32_gc->hcliprgn = NULL;
 
-  /* Use the same default values as X11 does, even if they don't make
-   * sense per se. But apps always set fg and bg anyway.
-   */
-  win32_gc->foreground = 0;
-  win32_gc->background = 1;
   win32_gc->font = NULL;
   win32_gc->rop2 = R2_COPYPEN;
-  win32_gc->fill_style = GDK_SOLID;
-  win32_gc->tile = NULL;
-  win32_gc->stipple = NULL;
   win32_gc->subwindow_mode = GDK_CLIP_BY_CHILDREN;
   win32_gc->graphics_exposures = TRUE;
   win32_gc->pen_width = 0;
@@ -485,8 +465,8 @@ gdk_win32_gc_get_values (GdkGC       *gc,
 {
   GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
 
-  values->foreground.pixel = win32_gc->foreground;
-  values->background.pixel = win32_gc->background;
+  values->foreground.pixel = _gdk_gc_get_fg_pixel (gc);
+  values->background.pixel = _gdk_gc_get_bg_pixel (gc);
   values->font = win32_gc->font;
 
   switch (win32_gc->rop2)
@@ -525,10 +505,9 @@ gdk_win32_gc_get_values (GdkGC       *gc,
       values->function = GDK_SET; break;
     }
 
-  values->fill = win32_gc->fill_style;
-
-  values->tile = win32_gc->tile;
-  values->stipple = win32_gc->stipple;
+  values->fill = _gdk_gc_get_fill (gc);
+  values->tile = _gdk_gc_get_tile (gc);
+  values->stipple = _gdk_gc_get_stipple (gc);
 
   /* Also the X11 backend always returns a NULL clip_mask */
   values->clip_mask = NULL;
@@ -608,51 +587,10 @@ gdk_win32_gc_set_dashes (GdkGC *gc,
 }
 
 void
-gdk_gc_set_clip_rectangle (GdkGC       *gc,
-                          GdkRectangle *rectangle)
-{
-  GdkGCWin32 *win32_gc;
-
-  g_return_if_fail (GDK_IS_GC (gc));
-
-  win32_gc = GDK_GC_WIN32 (gc);
-
-  if (win32_gc->hcliprgn)
-    DeleteObject (win32_gc->hcliprgn);
-
-  if (rectangle)
-    {
-      GDK_NOTE (GC, g_print ("gdk_gc_set_clip_rectangle: %p: %s\n",
-                            win32_gc,
-                            _gdk_win32_gdkrectangle_to_string (rectangle)));
-      win32_gc->hcliprgn = CreateRectRgn (rectangle->x, rectangle->y,
-                                         rectangle->x + rectangle->width,
-                                         rectangle->y + rectangle->height);
-      win32_gc->values_mask |= GDK_GC_CLIP_MASK;
-    }
-  else
-    {
-      GDK_NOTE (GC, g_print ("gdk_gc_set_clip_rectangle: NULL\n"));
-
-      win32_gc->hcliprgn = NULL;
-      win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
-    }
-
-  gc->clip_x_origin = 0;
-  gc->clip_y_origin = 0;
-  
-  win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
-} 
-
-void
-gdk_gc_set_clip_region (GdkGC    *gc,
-                       GdkRegion *region)
+_gdk_windowing_set_clip_region (GdkGC    *gc,
+                               GdkRegion *region)
 {
-  GdkGCWin32 *win32_gc;
-
-  g_return_if_fail (GDK_IS_GC (gc));
-
-  win32_gc = GDK_GC_WIN32 (gc);
+  GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
 
   if (win32_gc->hcliprgn)
     DeleteObject (win32_gc->hcliprgn);
@@ -681,46 +619,23 @@ gdk_gc_set_clip_region (GdkGC       *gc,
 }
 
 void
-gdk_gc_copy (GdkGC *dst_gc,
-            GdkGC *src_gc)
+_gdk_windowing_gc_copy (GdkGC *dst_gc,
+                       GdkGC *src_gc)
 {
-  GdkGCWin32 *dst_win32_gc;
-  GdkGCWin32 *src_win32_gc;
-
-  g_return_if_fail (GDK_IS_GC_WIN32 (dst_gc));
-  g_return_if_fail (GDK_IS_GC_WIN32 (src_gc));
-  
-  dst_win32_gc = GDK_GC_WIN32 (dst_gc);
-  src_win32_gc = GDK_GC_WIN32 (src_gc);
+  GdkGCWin32 *dst_win32_gc = GDK_GC_WIN32 (dst_gc);
+  GdkGCWin32 *src_win32_gc = GDK_GC_WIN32 (src_gc);
 
   GDK_NOTE (GC, g_print ("gdk_gc_copy: %p := %p\n", dst_win32_gc, src_win32_gc));
 
-  if (dst_gc->colormap)
-    g_object_unref (dst_gc->colormap);
-
   if (dst_win32_gc->hcliprgn != NULL)
     DeleteObject (dst_win32_gc->hcliprgn);
 
   if (dst_win32_gc->font != NULL)
     gdk_font_unref (dst_win32_gc->font);
 
-  if (dst_win32_gc->tile != NULL)
-    g_object_unref (dst_win32_gc->tile);
-
-  if (dst_win32_gc->stipple != NULL)
-    g_object_unref (dst_win32_gc->stipple);
-
   if (dst_win32_gc->pen_dashes)
     g_free (dst_win32_gc->pen_dashes);
   
-  dst_gc->clip_x_origin = src_gc->clip_x_origin;
-  dst_gc->clip_y_origin = src_gc->clip_y_origin;
-  dst_gc->ts_x_origin = src_gc->ts_x_origin;
-  dst_gc->ts_y_origin = src_gc->ts_y_origin;
-  dst_gc->colormap = src_gc->colormap;
-  if (dst_gc->colormap)
-    g_object_ref (dst_gc->colormap);
-
   dst_win32_gc->hcliprgn = src_win32_gc->hcliprgn;
   if (dst_win32_gc->hcliprgn)
     {
@@ -732,21 +647,11 @@ gdk_gc_copy (GdkGC *dst_gc,
     }
 
   dst_win32_gc->values_mask = src_win32_gc->values_mask; 
-  dst_win32_gc->foreground = src_win32_gc->foreground;
-  dst_win32_gc->background = src_win32_gc->background;
   dst_win32_gc->font = src_win32_gc->font;
   if (dst_win32_gc->font != NULL)
     gdk_font_ref (dst_win32_gc->font);
 
   dst_win32_gc->rop2 = src_win32_gc->rop2;
-  dst_win32_gc->fill_style = src_win32_gc->fill_style;
-  dst_win32_gc->tile = src_win32_gc->tile;
-  if (dst_win32_gc->tile != NULL)
-    g_object_ref (dst_win32_gc->tile);
-
-  dst_win32_gc->stipple = src_win32_gc->stipple;
-  if (dst_win32_gc->stipple != NULL)
-    g_object_ref (dst_win32_gc->stipple);
 
   dst_win32_gc->subwindow_mode = src_win32_gc->subwindow_mode;
   dst_win32_gc->graphics_exposures = src_win32_gc->graphics_exposures;
@@ -937,7 +842,7 @@ gdk_win32_hdc_get (GdkDrawable    *drawable,
 
   if (ok && (usage & GDK_GC_FOREGROUND))
     {
-      fg = _gdk_win32_colormap_color (impl->colormap, win32_gc->foreground);
+      fg = _gdk_win32_colormap_color (impl->colormap, _gdk_gc_get_fg_pixel (gc));
       if ((hbr = CreateSolidBrush (fg)) == NULL)
        WIN32_GDI_FAILED ("CreateSolidBrush"), ok = FALSE;
 
@@ -1259,23 +1164,3 @@ _gdk_win32_gdkregion_to_hrgn (GdkRegion *region,
 
   return (hrgn);
 }
-
-void
-_gdk_windowing_gc_get_foreground (GdkGC    *gc,
-                                 GdkColor *color)
-{
-  GdkGCWin32 *win32_gc;
-  GdkColormap *cmap;
-  
-  g_return_if_fail (GDK_IS_GC_WIN32 (gc));
-
-  win32_gc = GDK_GC_WIN32 (gc);
-
-  color->pixel = win32_gc->foreground;
-  cmap = gdk_gc_get_colormap (gc);
-
-  if (cmap)
-    gdk_colormap_query_color (cmap, win32_gc->foreground, color);
-  else
-    g_warning ("No colormap in _gdk_windowing_gc_get_foreground");
-}
index 0d1ab272def6efbf280bef09c6c8a99cdcc53efc..d5786a086ab6dd68905147b8c54415e52e8e0b0d 100644 (file)
@@ -268,14 +268,8 @@ struct _GdkGCWin32
 
   GdkGCValuesMask values_mask;
 
-  gulong foreground;           /* Pixel values from GdkColor, */
-  gulong background;           /* not Win32 COLORREFs */
-
   GdkFont *font;
   gint rop2;
-  GdkFill fill_style;
-  GdkPixmap *tile;
-  GdkPixmap *stipple;
   GdkSubwindowMode subwindow_mode;
   gint graphics_exposures;
   gint pen_width;
index c502ffa56cfa7f646ba902ad02357be8243082a0..71e02909f5e61900d875ee96d491a33ce0271d7c 100644 (file)
@@ -346,13 +346,13 @@ gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
 {
   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
   Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
-  GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL;
   Picture picture = gdk_x11_drawable_get_picture (drawable);
+  GdkRegion *clip_region = gc ? _gdk_gc_get_clip_region (gc) : NULL;
 
-  if (gc && gc_private->clip_region)
+  if (clip_region)
     {
-      GdkRegionBox *boxes = gc_private->clip_region->rects;
-      gint n_boxes = gc_private->clip_region->numRects;
+      GdkRegionBox *boxes = clip_region->rects;
+      gint n_boxes = clip_region->numRects;
       XRectangle *rects = g_new (XRectangle, n_boxes);
       int i;
 
index 806e96fe76ba197c0b14b6c1ac1ab75239270b90..2d0fe34a7b39eb862961a590f998b3012df130ee 100644 (file)
@@ -107,14 +107,6 @@ gdk_gc_x11_finalize (GObject *object)
 {
   GdkGCX11 *x11_gc = GDK_GC_X11 (object);
   
-  if (x11_gc->clip_region)
-    gdk_region_destroy (x11_gc->clip_region);
-  
-  if (x11_gc->stipple)
-    g_object_unref (x11_gc->stipple);
-  if (x11_gc->tile)
-    g_object_unref (x11_gc->tile);
-  
   XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -140,9 +132,10 @@ _gdk_x11_gc_new (GdkDrawable      *drawable,
   gc = g_object_new (_gdk_gc_x11_get_type (), NULL);
   private = GDK_GC_X11 (gc);
 
+  _gdk_gc_init (gc, drawable, values, values_mask);
+
   private->dirty_mask = 0;
   private->have_clip_mask = FALSE;
-  private->clip_region = NULL;
     
   private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
 
@@ -160,29 +153,6 @@ _gdk_x11_gc_new (GdkDrawable      *drawable,
       private->dirty_mask |= GDK_GC_DIRTY_TS;
     }
 
-  if (values_mask & GDK_GC_FOREGROUND)
-    private->fg_pixel = values->foreground.pixel;
-
-  if (values_mask & GDK_GC_BACKGROUND)
-    private->bg_pixel = values->background.pixel;
-
-  if (values_mask & GDK_GC_FILL)
-    private->fill = values->fill;
-  
-  if (values_mask & GDK_GC_STIPPLE)
-    {
-      private->stipple = values->stipple;
-      if (private->stipple)
-       g_object_ref (private->stipple);
-    }
-  
-  if (values_mask & GDK_GC_TILE)
-    {
-      private->tile = values->tile;
-      if (private->tile)
-       g_object_ref (private->tile);
-    }
-  
   if ((values_mask & GDK_GC_CLIP_MASK) && values->clip_mask)
     private->have_clip_mask = TRUE;
 
@@ -211,7 +181,9 @@ _gdk_x11_gc_flush (GdkGC *gc)
 
   if (private->dirty_mask & GDK_GC_DIRTY_CLIP)
     {
-      if (!private->clip_region)
+      GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
+      
+      if (!clip_region)
        XSetClipOrigin (xdisplay, xgc,
                        gc->clip_x_origin, gc->clip_y_origin);
       else
@@ -219,7 +191,7 @@ _gdk_x11_gc_flush (GdkGC *gc)
          XRectangle *rectangles;
           gint n_rects;
 
-          _gdk_region_get_xrectangles (private->clip_region,
+          _gdk_region_get_xrectangles (clip_region,
                                        gc->clip_x_origin,
                                        gc->clip_y_origin,
                                        &rectangles,
@@ -417,54 +389,10 @@ gdk_x11_gc_set_values (GdkGC           *gc,
 
   if (values_mask & GDK_GC_CLIP_MASK)
     {
-      if (x11_gc->clip_region)
-       {
-         gdk_region_destroy (x11_gc->clip_region);
-         x11_gc->clip_region = NULL;
-       }
-
+      x11_gc->have_clip_region = FALSE;
       x11_gc->have_clip_mask = values->clip_mask != NULL;
     }
 
-  if (values_mask & GDK_GC_FOREGROUND)
-    x11_gc->fg_pixel = values->foreground.pixel;
-
-  if (values_mask & GDK_GC_BACKGROUND)
-    {
-      if (x11_gc->bg_pixel != values->background.pixel)
-       x11_gc->bg_pixel = values->background.pixel;
-    }
-
-  if (values_mask & GDK_GC_FILL)
-    {
-      if (x11_gc->fill != values->fill)
-       x11_gc->fill = values->fill;
-    }
-  
-  if (values_mask & GDK_GC_STIPPLE)
-    {
-      if (x11_gc->stipple != values->stipple)
-       {
-         if (x11_gc->stipple)
-           g_object_unref (x11_gc->stipple);
-         x11_gc->stipple = values->stipple;
-         if (x11_gc->stipple)
-           g_object_ref (x11_gc->stipple);
-       }
-    }
-  
-  if (values_mask & GDK_GC_TILE)
-    {
-      if (x11_gc->tile != values->tile)
-       {
-         if (x11_gc->tile)
-           g_object_unref (x11_gc->tile);
-         x11_gc->tile = values->tile;
-         if (x11_gc->tile)
-           g_object_ref (x11_gc->tile);
-       }
-    }
-  
   gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
 
   XChangeGC (GDK_GC_XDISPLAY (gc),
@@ -704,158 +632,42 @@ gdk_x11_gc_values_to_xvalues (GdkGCValues    *values,
 
 }
 
-/**
- * gdk_gc_set_clip_rectangle:
- * @gc: a #GdkGC.
- * @rectangle: the rectangle to clip to.
- * 
- * Sets the clip mask for a graphics context from a
- * rectangle. The clip mask is interpreted relative to the clip
- * origin. (See gdk_gc_set_clip_origin()).
- **/
 void
-gdk_gc_set_clip_rectangle (GdkGC       *gc,
-                          GdkRectangle *rectangle)
+_gdk_windowing_gc_set_clip_region (GdkGC     *gc,
+                                  GdkRegion *region)
 {
-  GdkGCX11 *x11_gc;
-  gboolean had_region = FALSE;
-  
-  g_return_if_fail (GDK_IS_GC (gc));
-
-  x11_gc = GDK_GC_X11 (gc);
-
-  if (x11_gc->clip_region)
-    {
-      had_region = TRUE;
-      gdk_region_destroy (x11_gc->clip_region);
-    }
-
-  if (rectangle)
-    x11_gc->clip_region = gdk_region_rectangle (rectangle);
-  else
-    x11_gc->clip_region = NULL;
+  GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
 
   /* Unset immediately, to make sure Xlib doesn't keep the
    * XID of an old clip mask cached
    */
-  if ((had_region && !rectangle) || x11_gc->have_clip_mask)
+  if ((x11_gc->have_clip_region && !region) || x11_gc->have_clip_mask)
     {
       XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
       x11_gc->have_clip_mask = FALSE;
     }
 
-  gc->clip_x_origin = 0;
-  gc->clip_y_origin = 0;
-  
-  x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
-}
-
-/**
- * gdk_gc_set_clip_region:
- * @gc: a #GdkGC.
- * @region: the #GdkRegion. 
- * 
- * Sets the clip mask for a graphics context from a region structure.
- * The clip mask is interpreted relative to the clip origin. (See
- * gdk_gc_set_clip_origin()).
- **/
-void
-gdk_gc_set_clip_region (GdkGC    *gc,
-                       GdkRegion *region)
-{
-  GdkGCX11 *x11_gc;
-  gboolean had_region = FALSE;
-
-  g_return_if_fail (GDK_IS_GC (gc));
-
-  x11_gc = GDK_GC_X11 (gc);
-
-  if (x11_gc->clip_region)
-    {
-      had_region = TRUE;
-      gdk_region_destroy (x11_gc->clip_region);
-    }
-
-  if (region)
-    x11_gc->clip_region = gdk_region_copy (region);
-  else
-    x11_gc->clip_region = NULL;    
-
-  /* Unset immediately, to make sure Xlib doesn't keep the
-   * XID of an old clip mask cached
-   */
-  if ((had_region && !region) || x11_gc->have_clip_mask)
-    {
-      XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
-      x11_gc->have_clip_mask = FALSE;
-    }
+  x11_gc->have_clip_region = region != NULL;
 
   gc->clip_x_origin = 0;
   gc->clip_y_origin = 0;
-  
+
   x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
 }
 
-
-/**
- * gdk_gc_copy:
- * @dst_gc: the destination graphics context.
- * @src_gc: the source graphics context.
- * 
- * Copy the set of values from one graphics context
- * onto another graphics context.
- **/
 void
-gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
+_gdk_windowing_gc_copy (GdkGC *dst_gc,
+                       GdkGC *src_gc)
 {
-  GdkGCX11 *x11_src_gc;
-  GdkGCX11 *x11_dst_gc;
-  
-  g_return_if_fail (GDK_IS_GC_X11 (dst_gc));
-  g_return_if_fail (GDK_IS_GC_X11 (src_gc));
+  GdkGCX11 *x11_src_gc = GDK_GC_X11 (src_gc);
+  GdkGCX11 *x11_dst_gc = GDK_GC_X11 (dst_gc);
 
-  x11_dst_gc = GDK_GC_X11 (dst_gc);
-  x11_src_gc = GDK_GC_X11 (src_gc);
-  
   XCopyGC (GDK_GC_XDISPLAY (src_gc), GDK_GC_XGC (src_gc), ~((~1) << GCLastBit),
           GDK_GC_XGC (dst_gc));
 
-  dst_gc->clip_x_origin = src_gc->clip_x_origin;
-  dst_gc->clip_y_origin = src_gc->clip_y_origin;
-  dst_gc->ts_x_origin = src_gc->ts_x_origin;
-  dst_gc->ts_y_origin = src_gc->ts_y_origin;
-
-  if (src_gc->colormap)
-    g_object_ref (src_gc->colormap);
-
-  if (dst_gc->colormap)
-    g_object_unref (dst_gc->colormap);
-
-  dst_gc->colormap = src_gc->colormap;
-
-  if (x11_dst_gc->clip_region)
-    gdk_region_destroy (x11_dst_gc->clip_region);
-
-  if (x11_src_gc->clip_region)
-    x11_dst_gc->clip_region = gdk_region_copy (x11_src_gc->clip_region);
-  else
-    x11_dst_gc->clip_region = NULL;
-
   x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask;
-  x11_dst_gc->fg_pixel = x11_src_gc->fg_pixel;
-  x11_dst_gc->fill = x11_src_gc->fill;
-  
-  if (x11_dst_gc->stipple)
-    g_object_unref (x11_dst_gc->stipple);
-  x11_dst_gc->stipple = x11_src_gc->stipple;
-  if (x11_dst_gc->stipple)
-    g_object_ref (x11_dst_gc->stipple);
-  
-  if (x11_dst_gc->tile)
-    g_object_unref (x11_dst_gc->tile);
-  x11_dst_gc->tile = x11_src_gc->tile;
-  if (x11_dst_gc->tile)
-    g_object_ref (x11_dst_gc->tile);
+  x11_dst_gc->have_clip_region = x11_src_gc->have_clip_region;
+  x11_dst_gc->have_clip_mask = x11_src_gc->have_clip_mask;
 }
 
 /**
@@ -915,26 +727,5 @@ gdk_x11_gc_get_xgc (GdkGC *gc)
   return gc_x11->xgc;
 }
 
-void
-_gdk_windowing_gc_get_foreground (GdkGC    *gc,
-                                 GdkColor *color)
-{
-  GdkGCX11 *x11_gc;
-  GdkColormap *cmap;
-  
-  g_return_if_fail (GDK_IS_GC_X11 (gc));
-
-  x11_gc = GDK_GC_X11 (gc);
-
-  color->pixel = x11_gc->fg_pixel;
-
-  cmap = gdk_gc_get_colormap (gc);
-
-  if (cmap)
-    gdk_colormap_query_color (cmap, x11_gc->fg_pixel, color);
-  else
-    g_warning ("No colormap in _gdk_windowing_gc_get_foreground");
-}
-
 #define __GDK_GC_X11_C__
 #include "gdkaliasdef.c"
index 8554beb7625340d36c494a7aae7073926e56a65c..cde9042f6f49d1069c88eeebc062c3de3d940956 100644 (file)
@@ -59,17 +59,10 @@ struct _GdkGCX11
   
   GC xgc;
   GdkScreen *screen;
-  GdkRegion *clip_region;
   guint16 dirty_mask;
+  guint have_clip_region : 1;
   guint have_clip_mask : 1;
   guint depth : 8;
-
-  GdkFill fill;
-  GdkBitmap *stipple;
-  GdkPixmap *tile;
-
-  gulong fg_pixel;
-  gulong bg_pixel;
 };
 
 struct _GdkGCX11Class
index 10fb2f7e265bb25330b3dd9b441da316c5fa7cc0..7452c52e88903556a8f1aa7abab3d0b4868b9e8b 100644 (file)
@@ -2905,7 +2905,6 @@ draw_arrow (GdkWindow     *window,
   
   if (area)
     {
-      cairo_save (cr);
       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
       cairo_clip (cr);
       cairo_new_path (cr);
@@ -2939,9 +2938,6 @@ draw_arrow (GdkWindow     *window,
   cairo_close_path (cr);
   cairo_fill (cr);
 
-  if (area)
-    cairo_restore (cr);
-
   cairo_destroy (cr);
 }
 
@@ -3631,7 +3627,6 @@ gtk_default_draw_check (GtkStyle      *style,
       
   if (area)
     {
-      cairo_save (cr);
       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
       cairo_clip (cr);
       cairo_new_path (cr);
@@ -3726,9 +3721,6 @@ gtk_default_draw_check (GtkStyle      *style,
       cairo_fill (cr);
     }
   
-  if (area)
-    cairo_restore (cr);
-  
   cairo_destroy (cr);
 }
 
@@ -3759,7 +3751,6 @@ gtk_default_draw_option (GtkStyle      *style,
       
   if (area)
     {
-      cairo_save (cr);
       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
       cairo_clip (cr);
       cairo_new_path (cr);
@@ -3784,9 +3775,7 @@ gtk_default_draw_option (GtkStyle      *style,
                 (exterior_size - 1) / 2.,
                 0, 2 * G_PI);
 
-      cairo_save (cr);
-      cairo_fill (cr);
-      cairo_restore (cr);
+      cairo_fill_preserve (cr);
 
       if (type == BUTTON)
        gdk_cairo_set_source_color (cr, &style->fg[state_type]);
@@ -3853,9 +3842,6 @@ gtk_default_draw_option (GtkStyle      *style,
       cairo_fill (cr);
     }
   
-  if (area)
-    cairo_restore (cr);
-  
   cairo_destroy (cr);
 }
 
@@ -4811,7 +4797,6 @@ gtk_default_draw_expander (GtkStyle        *style,
   
   if (area)
     {
-      cairo_save (cr);
       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
       cairo_clip (cr);
       cairo_new_path (cr);
@@ -4888,7 +4873,6 @@ gtk_default_draw_expander (GtkStyle        *style,
   
   cairo_set_line_width (cr, line_width);
 
-  cairo_save (cr);
   if (state_type == GTK_STATE_PRELIGHT)
     gdk_cairo_set_source_color (cr,
                                &style->fg[GTK_STATE_PRELIGHT]);
@@ -4899,15 +4883,11 @@ gtk_default_draw_expander (GtkStyle        *style,
     gdk_cairo_set_source_color (cr,
                                &style->base[GTK_STATE_NORMAL]);
   
-  cairo_fill (cr);
-  cairo_restore (cr);
+  cairo_fill_preserve (cr);
   
   gdk_cairo_set_source_color (cr, &style->fg[state_type]);
   cairo_stroke (cr);
   
-  if (area)
-    cairo_restore (cr);
-
   cairo_destroy (cr);
 }
 
index 44ecea206b80265156f7587fb4f6fdf5bd3e2ac3..72b78f939cd04f8d0cfc1f7cbd1c71e8619df33d 100644 (file)
@@ -227,6 +227,8 @@ static gboolean         gtk_widget_real_can_activate_accel      (GtkWidget *widg
 static void gtk_widget_set_usize_internal (GtkWidget *widget,
                                           gint       width,
                                           gint       height);
+static void gtk_widget_get_draw_rectangle (GtkWidget    *widget,
+                                          GdkRectangle *rect);
 
 
 /* --- variables --- */
@@ -1456,6 +1458,12 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                                                               P_("Aspect ratio with which to draw insertion cursor"),
                                                               0.0, 1.0, 0.04,
                                                               GTK_PARAM_READABLE));
+  gtk_widget_class_install_style_property (klass,
+                                          g_param_spec_boxed ("draw-border",
+                                                              P_("Draw Border"),
+                                                              P_("Size of areas outside the widget's allocation to draw"),
+                                                              GTK_TYPE_BORDER,
+                                                              GTK_PARAM_READABLE));
 }
 
 static void
@@ -2430,6 +2438,55 @@ gtk_widget_queue_draw_area (GtkWidget *widget,
   gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE);
 }
 
+static void
+widget_add_child_draw_rectangle (GtkWidget    *widget,
+                                GdkRectangle *rect)
+{
+  GdkRectangle child_rect;
+  
+  if (!GTK_WIDGET_REALIZED (widget) ||
+      widget->window != widget->parent->window)
+    return;
+
+  gtk_widget_get_draw_rectangle (widget, &child_rect);
+  gdk_rectangle_union (rect, &child_rect, rect);
+}
+
+static void
+gtk_widget_get_draw_rectangle (GtkWidget    *widget,
+                              GdkRectangle *rect)
+{
+  if (GTK_WIDGET_NO_WINDOW (widget))
+    {
+      GtkBorder *draw_border = NULL;
+
+      *rect = widget->allocation;
+
+      gtk_widget_style_get (widget, 
+                           "draw-border", &draw_border,
+                           NULL);
+      if (draw_border)
+       {
+         rect->x -= draw_border->top;
+         rect->y -= draw_border->left;
+         rect->width += draw_border->left + draw_border->right;
+         rect->height += draw_border->top + draw_border->bottom;
+       }
+
+      if (GTK_IS_CONTAINER (widget))
+       gtk_container_forall (GTK_CONTAINER (widget),
+                             (GtkCallback)widget_add_child_draw_rectangle,
+                             rect);
+    }
+  else
+    {
+      rect->x = 0;
+      rect->y = 0;
+      rect->width = widget->allocation.width;
+      rect->height = widget->allocation.height;
+    }
+}
+
 /**
  * gtk_widget_queue_draw:
  * @widget: a #GtkWidget
@@ -2441,20 +2498,15 @@ gtk_widget_queue_draw_area (GtkWidget *widget,
 void      
 gtk_widget_queue_draw (GtkWidget *widget)
 {
+  GdkRectangle rect;
+  
   g_return_if_fail (GTK_IS_WIDGET (widget));
 
-  if (widget->allocation.width || widget->allocation.height)
-    {
-      if (GTK_WIDGET_NO_WINDOW (widget))
-       gtk_widget_queue_draw_area (widget, widget->allocation.x,
-                                   widget->allocation.y,
-                                   widget->allocation.width, 
-                                   widget->allocation.height);
-      else
-       gtk_widget_queue_draw_area (widget, 0, 0, 
-                                   widget->allocation.width, 
-                                   widget->allocation.height);
-    }
+  gtk_widget_get_draw_rectangle (widget, &rect);
+
+  gtk_widget_queue_draw_area (widget,
+                             rect.x, rect.y,
+                             rect.width, rect.height);
 }
 
 /* Invalidates the given area (allocation-relative-coordinates)
@@ -2687,11 +2739,13 @@ gtk_widget_invalidate_widget_windows (GtkWidget *widget,
 static void
 gtk_widget_queue_shallow_draw (GtkWidget *widget)
 {
+  GdkRectangle rect;
   GdkRegion *region;
   
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  
-  region = gdk_region_rectangle (&widget->allocation);
+
+  gtk_widget_get_draw_rectangle (widget, &rect);
+  region = gdk_region_rectangle (&rect);
   gtk_widget_invalidate_widget_windows (widget, region);
   gdk_region_destroy (region);
 }
@@ -3883,12 +3937,15 @@ GdkRegion *
 gtk_widget_region_intersect (GtkWidget *widget,
                             GdkRegion *region)
 {
+  GdkRectangle rect;
   GdkRegion *dest;
   
   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
   g_return_val_if_fail (region != NULL, NULL);
+
+  gtk_widget_get_draw_rectangle (widget, &rect);
   
-  dest = gdk_region_rectangle (&widget->allocation);
+  dest = gdk_region_rectangle (&rect);
  
   gdk_region_intersect (dest, region);